//
//  KeyManage.m
//  OpensslTest
//
//  Created by jiahua on 16/3/28.
//  Copyright © 2016年 secsmarts. All rights reserved.
//
//1、如果秘钥为空（第一次从App端先发送数据）或者收到的数据包的后16个字节为0（家电未连接路由器的时候），那么使用SN的hash
//2、如果收到的数据包的后16个字节不为0（家电已经连接上路由器了），解析出IP，通过Ip看是否存储了key值，没有的话，就需要通过这后16位来向云端发送
//
//

#import "KeyManage.h"
#import "sstNSStringFormat.h"
#import "sstNSDataFormat.h"
#import "HttpClient.h"
#import "DeviceManager.h"

static u8* wifiSsid;
static int ssidLen;
static u8* wifiPassword;
static int passwordLen;
static NSMutableDictionary *isOldDeviceFromIp;//用来判断家电是否为老家电
static NSMutableDictionary *isDeviceGetR3;//用来判断家电是否获取了R3，多个线程操作
static NSMutableDictionary *ipToSessionKey;//用来保存App和家电的会话秘钥，16进制字符串秘钥，多个线程操作
static NSMutableDictionary *ipToRandomKey1;//保存对应家电生成的key1值，16进制字符串
static NSMutableDictionary *ipToToken;//保存从云端请求下来的Token，用作之后秘钥协商发送
static NSMutableDictionary *ipToR3;//保存对应家电的R3，16进制字符串
static NSMutableDictionary *udpIDToIP;//保存对应家电UdpID的IP，其中UdpID为16进制字符串
static NSMutableDictionary *ipToSessionAndUdpID;//保存对应家电Session和UdpID
NSLock* sessionKeyLock;

@implementation KeyManage

//+(KeyManage *)getKeyManageInstance{
//    static dispatch_once_t pred;
//    static KeyManage *keyManage;
//    dispatch_once(&pred, ^{
//        keyManage = [[KeyManage alloc] init];
//    });
//
//    return keyManage;
//}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Config WIFI
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+(NSLock*)getSessionKeyLock{
    if(sessionKeyLock==nil){
        sessionKeyLock = [[NSLock alloc] init];
    }
    return sessionKeyLock;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Config WIFI
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+(void)setWIFIWithSSID:(NSString*)ssid withPassword:(NSString*)password{
}
+(u8*)getSSID{
    return wifiSsid;
}
+(int)getSSIDLen{
    return ssidLen;
}
+(u8*)getPassword{
    return wifiPassword;
}
+(int)getPasswordLen{
    return passwordLen;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Config OldDevice
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+(void)setOldDevice:(NSString*)old withIp:(NSString*)ip{
    if(isOldDeviceFromIp ==nil){
        isOldDeviceFromIp = [NSMutableDictionary dictionary];
    }
    [isOldDeviceFromIp setObject:old forKey:ip];
}

+(NSString*)getOldDevicefromIp:(NSString *)ip{
    if([isOldDeviceFromIp objectForKey:ip]){
        return [isOldDeviceFromIp objectForKey:ip];
    }
    return nil;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Config isDeviceGetR3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+(void)setIsDeviceGetR3:(NSString*)isGet withIp:(NSString*)ip{
    if(isDeviceGetR3 ==nil){
        isDeviceGetR3 = [NSMutableDictionary dictionary];
    }
    [isDeviceGetR3 setObject:isGet forKey:ip];
}

+(NSString*)getIsDeviceGetR3fromIp:(NSString *)ip{
    if([isDeviceGetR3 objectForKey:ip]){
        return [isDeviceGetR3 objectForKey:ip];
    }
    return @"NO";
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark RandomKey1
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+(NSString *)generatorRandomkey1WithIP:(NSString*)ip{
    if( ipToRandomKey1==nil){
        ipToRandomKey1 = [NSMutableDictionary dictionary];
    }
    Byte randomKey1[32];
    get_random_bytes(randomKey1, 32);
    //生成key1随机数，32字节，然后转换成16进制NSString类型存储
    NSLog(@"生成的秘钥Key为-->%@", [sstNSStringFormat Byte2HexNSString:randomKey1 withLength:32]);
    [ipToRandomKey1 setObject:[sstNSStringFormat Byte2HexNSString:randomKey1 withLength:32] forKey:ip];
    
    return [sstNSStringFormat Byte2HexNSString:randomKey1 withLength: LICENSE_INIT_KEY_LEN];
}


+(u8*)getRandomKey1fromIp:(NSString *)ip{
    if([ipToRandomKey1 objectForKey:ip]){
        NSLog(@"获得的秘钥key1为-->%@", [ipToRandomKey1 objectForKey:ip]);
        return [sstNSStringFormat NSString2Char:[ipToRandomKey1 objectForKey:ip]];
    }
    return nil;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark SessionKey
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//因为几个线程同时访问sessionKey，所以在生成sessionkey时加了锁。
+(void)generatorSessionKey:(u8*)key2 withIp:(NSString*)ip{
//    [[KeyManage getSessionKeyLock] lock];
    if( ipToSessionKey==nil){
        ipToSessionKey = [NSMutableDictionary dictionary];
    }
    u8 sessionKey[32];
    u8 key1[32];
    CharToByte([KeyManage getRandomKey1fromIp:ip], 64, key1);
    [KeyManage xorData:sessionKey withInput1:key1 withInput2:key2 withLen:32];
    [ipToSessionKey setObject:[sstNSStringFormat Byte2HexNSString:sessionKey withLength:32] forKey:ip];
//    [[KeyManage getSessionKeyLock] unlock];
}

+(u8*)getSessionKeyfromIp:(NSString *)ip{
    if([ipToSessionKey objectForKey:ip]){
        NSLog(@"获得的秘钥为-->%@", [ipToSessionKey objectForKey:ip]);
        return [sstNSStringFormat NSString2Char:[ipToSessionKey objectForKey:ip]];
    }
    return nil;
}
+(void)removeSessionKeyWithIP:(NSString*)ip{
    [ipToSessionKey removeObjectForKey:ip];
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark ipToToken
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+(void)setIpToToken:(NSString*)token withIp:(NSString*)ip{
    if( ipToToken==nil){
        ipToToken = [NSMutableDictionary dictionary];
    }
    [ipToToken setObject:token forKey:ip];
}

+(u8*)getIpToTokenWithIp:(NSString *)ip{
    if([ipToToken objectForKey:ip]){
        NSLog(@"获得的秘钥为-->%@", [ipToToken objectForKey:ip]);
        return [sstNSStringFormat NSString2Char:[ipToToken objectForKey:ip]];
    }
    return nil;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Config R3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

+(void)generatorR3WithSSID:(const u8*)ssid withPassword:(const u8*)password withMac:(const u8*)mac withIP:(NSString*)ip{
    if( ipToR3==nil){
        ipToR3 = [NSMutableDictionary dictionary];
    }
    
    int ssidlen = [KeyManage getSSIDLen];
    int pwlen = [KeyManage getPasswordLen];
    int maclen = 6;
    
    u8 *buf = malloc(ssidlen + pwlen + maclen);
    u8 macByte[6];
    CharToByte(mac, maclen * 2, macByte);
    
    memcpy(buf, ssid, ssidlen);
    memcpy(buf + ssidlen, password, pwlen);
    memcpy(buf + ssidlen + pwlen, macByte, maclen);
    //hash(SSID+口令+Mac)=R3
    u8 hashOutData[32];
    SHA256(buf, ssidlen+pwlen+maclen, hashOutData);
    [ipToR3 setObject:[sstNSStringFormat Byte2HexNSString:hashOutData withLength:32] forKey:ip];
    //NSLog(@"generatorR3WithSSID=  %@", [sstNSStringFormat Byte2HexNSString: hashOutData withLength : 32]);
    free(buf);
}

+(void)generatorR3WithSSID: (SstDevice *)device withWifi: (SstWifi *) wifi
{
    NSUInteger ssidlen = wifi.ssid.length;
    NSUInteger pwlen = wifi.password.length;
    NSUInteger maclen = LICENSE_MAC_LEN;
    
    u8 *buf = malloc(ssidlen + pwlen + maclen);
    u8 macByte[LICENSE_MAC_LEN] = {0};
    CharToByte((const u8 *)[sstNSStringFormat NSString2Char: device.mac], (int)maclen * 2, (u8 *)macByte);
   // LogHex("macByte------> ", macByte, 6);
    
    memcpy(buf, [sstNSStringFormat NSString2Char: wifi.ssid], ssidlen);
    memcpy(buf + ssidlen, [sstNSStringFormat NSString2Char: wifi.password], pwlen);
    memcpy(buf + ssidlen + pwlen, macByte, maclen);
    
    //hash(SSID+口令+Mac)=R3
    u8 hashOutData[HASH_DIGEST_LEN] = {0};
    //LogHex("buf------> ", buf, (int)(ssidlen + pwlen + maclen));
    SHA256(buf, ssidlen + pwlen + maclen, hashOutData);
    //LogHex("R3------> ", hashOutData, HASH_DIGEST_LEN);
    device.ssidKey = hashOutData;
}

+(u8*)getDiscussKeyR3fromIp:(NSString *)ip{
    //如果不为0，先在管理器中通过IP查找
    if([ipToR3 objectForKey:ip]){
        NSLog(@"获得的秘钥R3为-->%@", [ipToR3 objectForKey:ip]);
        return [sstNSStringFormat NSString2Char:[ipToR3 objectForKey:ip]];
    }
    return nil;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Config udpIDToIP
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+(void)setUdpIDToIP:(NSString*)deviceID withIp:(NSString*)ip{
    if(udpIDToIP ==nil){
        udpIDToIP = [NSMutableDictionary dictionary];
    }
    [udpIDToIP setObject:ip forKey:deviceID];
}

+(NSString*)getIPfromUdpIDToIPwith:(NSString *)deviceID{
    //通过DeviceID找到对应的IP
    if([udpIDToIP objectForKey:deviceID]){
        return [udpIDToIP objectForKey:deviceID];
    }
    return nil;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Config ipToSessionAndUdpID
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//这里sessionId和udpId都是NSString类型的
+(void)setIpToSessionAndUdpID:(NSString*)sessionID withUdpID:(NSString*)udpID withIP:(NSString*)ip{
    if(ipToSessionAndUdpID ==nil){
        ipToSessionAndUdpID = [NSMutableDictionary dictionary];
    }
    NSArray* array = [[NSArray alloc] initWithObjects:sessionID, udpID, nil];
    [ipToSessionAndUdpID setObject:array forKey:ip];
}

+(NSArray*)getIpToSessionAndUdpID:(NSString *)ip{
    if([ipToSessionAndUdpID objectForKey:ip]){
        return [ipToSessionAndUdpID objectForKey:ip];
    }
    return nil;
}

/**
 *  input1和input2异或返回outData
 *
 *  @param outData <#outData description#>
 *  @param input1  <#input1 description#>
 *  @param input2  <#input2 description#>
 *  @param length  <#length description#>
 */
+(void)xorData:(u8 *)outData withInput1:(const u8* const)input1 withInput2:(const u8* const)input2 withLen:(const long)length{
    long i = 0;
    for (i = 0; i < length; i ++){
        outData[i] = input1[i] ^ input2[i];
    }
}

/**
 *  从云端获取家电的Toke
 *
 *  @param device
 *
 *  @return void
 */
+(void)getTokenForDeviceFromCloud: (SstDevice *)device
{
    if (device == nil)
    {
        NSLog(@"getTokenForDeviceFromCloud device = nil");
        return;
    }
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSString *hexUdpKeyID = [sstNSStringFormat Byte2HexNSString: device.hexUdpKeyID withLength: UDP_KEY_ID_LEN];
        NSData* response = [HttpClient getTokenBySessionAndUdpid: [DeviceManager Instance].sessionID withUdpId:hexUdpKeyID];
        if (response == nil)
            return;
        
        NSError* error;
        NSArray* arrayResult = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
        for(int i=0; i<[arrayResult count]; i++)
        {
            NSDictionary* currentResult = [arrayResult objectAtIndex:i];
            NSString *k1Str = [currentResult objectForKey:@"key"];
            NSLog(@"k1Str = %@", k1Str);
            
            u8* k1u8 = [sstNSStringFormat NSString2Char: k1Str];
            u8 k1[HASH_DIGEST_LEN] = {0};
            [sstNSStringFormat CharToByte: k1u8 withLen: LICENSE_KEY_LEN * 2 outBuf: k1];
            device.k1 = k1;
            /*
                        u8 k1Hash[SST_HASH_SIZE] = {0};
                        u8 k1[HASH_DIGEST_LEN] = {0};
                        GetHash(k1, HASH_DIGEST_LEN, k1Hash);
                        LogHex("Hash(k1)", k1Hash, HASH_DIGEST_LEN);
                        */
            NSString *tokenStr = [currentResult objectForKey:@"token"];
            NSLog(@"token = %@", tokenStr);
            
            if(tokenStr.length != TOKEN_LENGTH * 2)
            {
                NSLog(@"从云端取回token.length = %d 长度应该为%d", (int)tokenStr.length, TOKEN_LENGTH * 2);
                break;
            }
            u8 u8Token[TOKEN_LENGTH] = {0};
            [sstNSStringFormat CharToByte: [sstNSStringFormat NSString2Char: tokenStr] withLen: TOKEN_LENGTH * 2 outBuf: u8Token];
            
            device.hexToken = u8Token;
            device.hasGetR3 = true;
        }
    });
}

/**
 *  由deviceId转换成UdpId
 *    1)hash(deviceID)
 *    2)前16字节和后16字节进行异或形成最后的Udp_ID
 *
 *  @param deviceId deviceId description
 *
 *  @return 返回NSString类型的UdpId
 */
+(void)deviceId2UdpId:(const u8* const)deviceId udpKeyId:(u8 *)udpKeyId
{
    
    u8 hashData[HASH_DIGEST_LEN] = {0};
    //DeviceId是不是32位？
    SHA256(deviceId, HASH_DIGEST_LEN, hashData);
    
    u8* headData = hashData;
    u8* tailData = hashData + HASH_DIGEST_LEN - UDP_KEY_ID_LEN;
    [KeyManage xorData: udpKeyId withInput1:headData withInput2:tailData withLen: UDP_KEY_ID_LEN];
    
    LogHex("udpKeyId", udpKeyId, UDP_KEY_ID_LEN);
}


/**
 *  获取 NSData 数据尾部16个字节
 *
 *  @param data 传入的NSData格式数据
 *
 *  @return 返回数据尾部后16字节
 */ 
+(u8 *)getTail16String:(const u8 *)data  dataLen: (int) datalen
{
    const u8* tail =  data + datalen - UDP_KEY_ID_LEN;
    LogHex("tail", tail, UDP_KEY_ID_LEN);
    
    return (u8*)tail;
}

+(int)isZeroTail:(const u8 *)data
{
    u8 zero[UDP_KEY_ID_LEN] = {0x0};
    return memcmp(data, zero, UDP_KEY_ID_LEN) == 0;
}
@end
